'use strict';

let model = require('../../model/mongo/category.js');
let debug = require('debug')('category');
let fout = require('../../common/function.js').formatOutput;

function MongoDao() {
    let self = this instanceof MongoDao ? this : new MongoDao();
    return self;
}
module.exports = MongoDao;
let theProto = MongoDao.prototype;

theProto.findByName = function*(name) {
    debug('findByName, name=' + name);
    let errCode = 0;
    let errMsg = null;
    let data = null;

    try {
        let result = yield model.findOne({name: name});
        errMsg = result.errors;
        data = result._doc;
        if (!data) errMsg = name + ' not exists';
    } catch (e) {
        errMsg = e.toString();
    }
    if (errMsg) {
        errCode = 10003;
        errMsg = 'category: find by name error,' + errMsg;
    }

    return fout(errCode, errMsg, data);
};

theProto.findByLevel = function*(level) {
    debug('findByLevel, level=' + level);
    let errCode = 0;
    let errMsg = null;
    let data = null;
    try {
        let result = yield model.find({level: level});
        errMsg = result.errors;
        data = result._doc;
    } catch (e) {
        return e.toString();
    }
    if (errMsg) {
        errCode = 10004;
        errMsg = 'category: find by level error,' + errMsg;
    }
    return fout(errCode, errMsg, data);
};

theProto.saveOne = function*(json) {
    let errCode = 0;
    let errMsg = null;

    let level = 1; // default , level = 1
    if (json.pName) {
        let parent = yield this.findByName(json.pName);
        parent = parent.result;
        if (parent === null) {
            errCode = 10001;
            errMsg = "category: pName not exists";
            return fout(errCode, errMsg);
        } else {
            level = parent.level + 1;
            // update parent
            let p = yield model.findOneAndUpdate(
                {_id: parent._id.toString()},
                {$push: {subName: json.name}}
            );
            if (p.errors) {
                errCode = 10002;
                errMsg = "category: add to parent error";
                return fout(errCode, errMsg);
            }
        }
    }

    let item = {
        name: json.name,
        pName: json.pName || null,
        level: level
    };

    // save
    let cate = new model(item);
    let data;
    try {
        let result = yield cate.save();
        errMsg = result.errors;
        data = result._doc;
    } catch (e) {
        errMsg = e.toString();
    }
    if (errMsg) {
        errCode = 10005;
        errMsg = 'category: duplicate name=' + json.name + errMsg;
    }

    return fout(errCode, errMsg, data);
};


/**save many category*/
theProto.saveMany = function*(json) {
    if (!Array.isArray(json)) {
        json = [json];
    }

    for (let i = 0; i < json.length; i++) {
        let ret = yield this.saveTree(json[i]);
        if (ret.errCode !== 0) {
            return ret;
        }
    }

    return fout(0, null, {success: true});
};

/**
 *
 * @param tree
 * @returns {*}
 */
theProto.saveTree = function*(tree) {
    let entity = {name: tree.name};
    if (tree.pName) {
        entity.pName = tree.pName;
    }

    let result = yield this.saveOne(entity);
    if (result.errCode !== 0) {
        return result;
    }

    if (tree.sub && tree.sub.length > 0) {
        tree.sub.forEach(function (item) {
            item.pName = tree.name;
        });
        let result = yield this.saveMany(tree.sub);
        if (result.errCode !== 0) {
            return result;
        }
    }
    return fout(0, null, {success: true});
};

/**
 * 检测某项category是否存在, TODO,可以优化,只find一次
 * @param cates
 */
theProto.exists = function*(cates) {
    let ret = {};
    for (let i = 0; i < cates.length; i++) {
        let n = cates[i];
        let r = yield this.findByName(n);
        ret[n] = r.errCode === 0;
    }
    return fout(0, null, ret);
};